<?php
/**
 * Base Model
 *
 * PHP Version 5.4
 *
 * @author baohui <baohui@icesmart.cn>
 */

namespace Model;
use Think\Model;

/**
 * Class BaseModel
 */
abstract class BaseModel extends Model
{
    /**
     * table name
     *
     * @var string
     */
    protected $primaryKey = null;

    /**
     * construct
     */
    public function __construct()
    {
        if (empty($this->primaryKey)) {
            $pk = $this->getPk();
            if (empty($pk)) {
                throw new ModelException($this, 'please check table primary key sets', 500);
            }
            $this->primaryKey = $pk;
        }

        if (empty($this->tableName)) {
            throw new Exception('table name not set in base model');
        }

        parent::__construct($this->tableName);
    }

    /**
     * get by id
     *
     * @param int $id user id
     *
     * @return null
     */
    public function get($id)
    {
        $result = $this->where("`{$this->primaryKey}`='{$id}'")->find();
        if (empty($result)) {
            return null;
        } else {
            return $result;
        }
    }

    /**
     * update row by row id
     *
     * @param array $data data
     * @param int   $pkId
     *
     * @throws ModelException
     *
     * @return bool|void
     */
    public function update(Array $data, $pkId=null)
    {
        if (isset($data[$this->primaryKey])
            && !empty($data[$this->primaryKey])
        ) {
            $pkId = $data[$this->primaryKey];
            unset($data[$this->primaryKey]);
        }
        if (empty($pkId)) {
            throw new ModelException($this, 'primary id not found', 500);
        }

        return parent::save(
            $data,
            [
                'where'=>[
                    $this->primaryKey=>$pkId
                ]
            ]
        );
    }

    /**
     * find multi rows by filter
     *
     * @param array $filter
     * @param array $order
     * @param array $limit
     *
     * @return array|null
     */
    public function findByFilter(Array $filter, Array $order=[], $limit=null)
    {
        if (!is_null($limit)) {
            $this->limit($limit[0], $limit[1]);
        }

        if (!empty($order)) {
            $orderArray = [];
            foreach ($order as $field=>$sort) {
                if (empty($sort)) {
                    $sort = 'ASC';
                }
                $orderArray[]="`{$field}` {$sort}";
            }
            if (!empty($orderArray)) {
                $this->order(implode(',', $orderArray));
            }
        }

        return $this->buildQueryFilter($filter)->select();
    }

    /**
     * count by filter
     *
     * @param array $filter
     *
     * @return int
     */
    public function countByFilter(Array $filter)
    {
        $result = $this->buildQueryFilter($filter)->count();
        if($result){
            return $result;
        }else{
            return 0;
        }
    }

    /**
     * build query filter
     *
     * @param array $filter filter
     *
     * @return Model
     */
    public function buildQueryFilter(Array $filter)
    {
        if (empty($filter)) {
            return $this;
        }
        $whereArray = [];

        foreach ($filter as $field=>$value) {
            $whereArray[] = "`{$field}`='{$value}'";
        }
        $whereStr = '';

        if (!empty($whereArray)) {
            $whereStr = implode(' AND ', $whereArray);
        }

        if (!empty($whereStr)) {
            $this->where($whereStr);
        }

        return $this;
    }

    /**
     * 按$group 分组 并统计各组的列数
     * @param array $group
     * @param array $filter filter
     *
     * @return array| null
     */
    public function groupFilter(Array $group, Array $filter=[])
    {
        if(empty($group)){
            return null;
        }

        if(!empty($filter)){
            $this->buildQueryFilter($filter);
        }
        $group = implode(',', $group);
        $this->group($group);

        return $this->field($group.',count(*) count')->select();
    }
}